package com.treepoke.util.database;

import com.treepoke.util.date.DateUtil;
import com.treepoke.util.dto.FiltroSQLDTO;
import com.treepoke.util.exception.DataAccessException;
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import javax.persistence.Query;
import javax.persistence.TemporalType;

public class DatabaseUtil {

    /**
     * Agrega una nueva condición a una sentencia SQL.
     *
     * @param valorFiltro
     * @param campoFiltro
     * @param sqlSentencia
     * @return <i>true</i> si se agrego el filtro exitosamente, <i>false</i> en
     * caso contrario.
     * @author Ricardo Cortes - ITAC @modifiedby ELTV
     */
    public static boolean agregarCampoFiltro(Object valorFiltro, String campoFiltro,
            StringBuilder sqlSentencia, FiltroSQLDTO filtroSQLDTO) {
        boolean retorno = false;
        if (valorFiltro != null) {
            String conector = " and ";
            if (!filtroSQLDTO.isInicializado()) {
                conector = " where ";
                filtroSQLDTO.setInicializado(true);
            }
            sqlSentencia.append(conector);
            sqlSentencia.append(campoFiltro);
            sqlSentencia.append(" ");
            sqlSentencia.append(filtroSQLDTO.getOperadorComparacion().getDescripcionSQL());
            sqlSentencia.append(" ?");
            retorno = true;
        }

        return retorno;
    }

    /**
     * Agrega un nuevo valor a un objecto PreparedStatement
     *
     * @param sentencia
     * @param valorFiltro
     * @param idParameter
     * @return <i>true</i> si se agrego el filtro exitosamente, <i>false</i> en
     * caso contrario.
     * @author ELTV
     * @throws SQLException
     * @throws ParseException
     */
    public static boolean agregarValorFiltro(PreparedStatement sentencia, Object valorFiltro,
            FiltroSQLDTO filtroSQLDTO) throws DataAccessException {
        boolean retorno = false;
        if (valorFiltro != null) {
            int idParameter = filtroSQLDTO.getIndiceParametro();
            try {
                if (valorFiltro instanceof Integer) {
                    sentencia.setInt(idParameter++, (Integer) valorFiltro);
                } else if (valorFiltro instanceof Long) {
                    sentencia.setLong(idParameter++, (Long) valorFiltro);
                } else if (valorFiltro instanceof Calendar) {
                    sentencia.setTimestamp(idParameter++,
                            DateUtil.getTimestampFromCalendar((Calendar) valorFiltro));
                } else if (valorFiltro instanceof String) {
                    sentencia.setString(idParameter++, (String) valorFiltro);
                } else if (valorFiltro instanceof BigDecimal) {
                    sentencia.setBigDecimal(idParameter++, (BigDecimal) valorFiltro);
                } else if (valorFiltro instanceof Boolean) {
                    sentencia.setBoolean(idParameter++, (Boolean) valorFiltro);
                } else if (valorFiltro instanceof Date) {
                    sentencia.setTimestamp(idParameter++,
                            DateUtil.getTimestampFromDate((Date) valorFiltro));
                } else {
                    throw new DataAccessException("Tipo de dato no soportado: " + valorFiltro.getClass(), 0);
                }
            } catch (SQLException ex) {
                throw new DataAccessException("Error en interacción con BD: " + ex.getMessage(), ex, 0);
            }
            filtroSQLDTO.setIndiceParametro(idParameter);
            retorno = true;
        }

        return retorno;
    }

    /**
     * Agrega una nueva condición a una sentencia JPQL.
     *
     * @param valorFiltro
     * @param campoFiltro
     * @param campo
     * @param sqlSentencia
     * @return <i>true</i> si se agrego el filtro exitosamente, <i>false</i> en
     * caso contrario.
     * @author ELTV - ITAC @modifiedby dpulido
     */
    public static boolean agregarCampoFiltroJPQL(Object valorFiltro, String campoFiltro, String campo,
            StringBuilder sqlSentencia, FiltroSQLDTO filtroSQLDTO) {
        boolean retorno = false;
        if (valorFiltro != null) {
            String conector = " and ";
            if (!filtroSQLDTO.isInicializado()) {
                conector = " where ";
                filtroSQLDTO.setInicializado(true);
            }
            sqlSentencia.append(conector);
            sqlSentencia.append(campoFiltro);
            sqlSentencia.append(" ");
            sqlSentencia.append(filtroSQLDTO.getOperadorComparacion().getDescripcionSQL());
            if (!(filtroSQLDTO.getOperadorComparacion().getDescripcionSQL().equalsIgnoreCase("is null"))) {
                sqlSentencia.append(" :");
                sqlSentencia.append(campo);
            }
            retorno = true;
        }

        return retorno;
    }

    /**
     * Agrega un nuevo valor a un objecto Query
     *
     * @param sentencia
     * @param valorFiltro
     * @param idParameter
     * @return <i>true</i> si se agrego el filtro exitosamente, <i>false</i> en
     * caso contrario.
     * @author ELTV @modifiedby dpulido
     * @throws ParseException
     */
    public static boolean agregarValorFiltroJPQL(Query sentencia, Object valorFiltro,
            String campoFiltro, FiltroSQLDTO filtroSQLDTO) throws DataAccessException {
        boolean retorno = false;
        if (valorFiltro != null) {

            if (valorFiltro instanceof Integer) {
                sentencia.setParameter(campoFiltro, (Integer) valorFiltro);
            } else if (valorFiltro instanceof Long) {
                sentencia.setParameter(campoFiltro, (Long) valorFiltro);
            } else if (valorFiltro instanceof Calendar) {
                sentencia.setParameter(campoFiltro,
                        DateUtil.getTimestampFromCalendar((Calendar) valorFiltro));
            } else if (valorFiltro instanceof String) {
                sentencia.setParameter(campoFiltro, (String) valorFiltro);
            } else if (valorFiltro instanceof BigDecimal) {
                sentencia.setParameter(campoFiltro, (BigDecimal) valorFiltro);
            } else if (valorFiltro instanceof Boolean) {
                sentencia.setParameter(campoFiltro, (Boolean) valorFiltro);
            } else if (valorFiltro instanceof Short) {
                sentencia.setParameter(campoFiltro, (Short) valorFiltro);
            } else if (valorFiltro instanceof Date) {
                /*
                 * sentencia.setParameter(campoFiltro, (Date) valorFiltro, TemporalType.DATE);
                 */
                sentencia.setParameter(campoFiltro,
                        DateUtil.getTimestampFromDate((Date) valorFiltro));
            } else {
                throw new DataAccessException("Tipo de dato no soportado: " + valorFiltro.getClass(), 0);
            }
            retorno = true;
        }

        return retorno;
    }
}
